package com.opdar.platform.core.session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by jeffrey on 2016/11/13.
 */
public class MemorySessionManager<T> implements ISessionManager<T> {
    private ConcurrentHashMap<String,SessionTask> sessions = new ConcurrentHashMap<String, SessionTask>();
    private ExecutorService executorService = Executors.newCachedThreadPool();
    private Logger logger = LoggerFactory.getLogger("SessionManager");
    private AtomicBoolean isDestory = new AtomicBoolean(false);

    public void set(String token,T users,long timeout){
        SessionTask task = null;
        sessions.put(token,task = new SessionTask(token,users,timeout));
        executorService.execute(task);
    }

    public String set(T users,long timeout){
        String token = UUID.randomUUID().toString();
        this.set(token,users,timeout);
        logger.debug("用户「{}」登陆.",token);
        return token;
    }

    @Override
    public T get(String token) {
        return sessions.containsKey(token)? (T) sessions.get(token).getUsersEntity() :null;
    }

    @Override
    public void clearTimeout(String token) {
        sessions.get(token).clearTimeout();
    }

    @Override
    public void destory() {
        executorService.shutdown();
    }

    public void remove(String token){
        sessions.remove(token);
    }

    private class SessionTask implements Runnable {
        private String token;
        private T usersEntity;
        private long timeout = 60*1000;
        private long lastRefreshTime = System.currentTimeMillis();
        private AtomicBoolean isRunning = new AtomicBoolean(true);

        T getUsersEntity() {
            return usersEntity;
        }

        SessionTask(String token, T usersEntity, long timeout) {
            this.token = token;
            this.usersEntity = usersEntity;
            this.timeout = timeout;
        }

        void clearTimeout(){
            lastRefreshTime = System.currentTimeMillis();
        }

        @Override
        public void run() {
            while (isRunning.get() && !MemorySessionManager.this.isDestory.get()){
                long t = System.currentTimeMillis() - lastRefreshTime;
                if(t >= timeout){
                    //超时
                    isRunning.set(false);
                    logger.debug("用户「{}」登陆超时",token);
                    MemorySessionManager.this.remove(token);
                }else{
                    long nextScheduleTime = timeout - t;
                    try {
                        Thread.sleep(nextScheduleTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
